﻿// ----------------------------------------------------------------------------
//  Copyright (C) 成都联宇创新科技有限公司 版权所有。 
//      
//  文件名：WindowsHostedService.cs
//  文件功能描述：
//  创建标识：骆智慧 2016/03/03 00:00
//     
//  修改标识：骆智慧  2016/03/10/06:40
//  修改描述：
//  ----------------------------------------------------------------------------

#region 导入名称空间

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Autofac;
using Common.Logging;
using LightWork.Topshelf.Autofac;

#endregion

namespace LightWork.Services
{
    /// <summary>
    /// Windows服务宿主管理服务，控制托管于此服务的服务的运行状态
    /// </summary>
    [Serializable]
    public class WindowsHostedService : IDisposable
    {
        private static List<IHostedService> _hostedServices = new List<IHostedService>();
        private readonly ILog _log = LogManager.GetLogger<WindowsHostedService>();

        #region IDisposable 成员

        public void Dispose()
        {
            try
            {
                _hostedServices.ForEach(hostedService => hostedService.Dispose());
            }
            catch (Exception ex)
            {
                _log.Error(ex);
            }
        }

        #endregion

        #region Methodes

        public static IEnumerable<TService> GetAllInstances<TService>(IEnumerable<object> IEnumerable)
        {
            return IEnumerable.Select(item => (TService) item);
        }

        /// <summary>
        /// 初始化服务
        /// </summary>
        /// <returns></returns>
        public bool Initialize()
        {
            try
            {
                var container = AutofacHostBuilderConfigurator.LifetimeScope;
                var type = typeof(IEnumerable<>).MakeGenericType(typeof(IHostedService));
                var tmpServices =
                    GetAllInstances<IHostedService>(((IEnumerable) container.Resolve(type)).Cast<object>());
                _hostedServices = tmpServices as List<IHostedService> ?? tmpServices.ToList();

                return !_hostedServices.Any() || _hostedServices.All(service =>
                {
                    try
                    {
                        service.Initialize();
                        return true;
                    }
                    catch
                    {
                        return false;
                    }
                });
            }
            catch (Exception ex)
            {
                _log.Fatal(ex);
                return false;
            }
        }


        /// <summary>
        /// 执行动作
        /// </summary>
        /// <param name="exceptState"></param>
        /// <param name="callbackAction"></param>
        /// <param name="msgType"></param>
        /// <param name="orderByKeySelector"></param>
        /// <returns></returns>
        private bool ServiceAction(CustomerServiceState exceptState, Func<IHostedService, bool> callbackAction,
            string msgType, Func<IHostedService, int> orderByKeySelector = null)
        {
            try
            {
                if (!_hostedServices.Any())
                    return true;

                var tmpCollection = orderByKeySelector != null
                    ? _hostedServices.OrderBy(orderByKeySelector).ToList()
                    : _hostedServices;

                foreach (var hostedService in tmpCollection)
                {
                    _log.DebugFormat("{0} {1} ……", msgType, hostedService.ServiceName);
                    var result = hostedService.CurrentState == exceptState || callbackAction(hostedService);
                    hostedService.CurrentState = result ? exceptState : hostedService.CurrentState;
                    if (!result)
                    {
                        _log.ErrorFormat("{0} {1} {2} ", msgType, hostedService.ServiceName, "失败");
                        return false;
                    }

                    _log.DebugFormat("{0} {1} {2} ", msgType, hostedService.ServiceName, "成功");
                }

                return true;
            }
            catch (Exception ex)
            {
                _log.Error(ex);
                return false;
            }
        }

        #endregion

        #region Interface implement

        /// <summary>
        /// 启动服务
        /// </summary>
        /// <returns></returns>
        public bool Start()
        {
            return Initialize() &&
                   ServiceAction(CustomerServiceState.Started, hostedService => hostedService.Start(), "启动",
                       hostedService => hostedService.StartIndex);
        }

        /// <summary>
        /// 停止服务
        /// </summary>
        /// <returns></returns>
        public bool Stop()
        {
            return ServiceAction(CustomerServiceState.Stoped, hostedService => hostedService.Stop(), "停止",
                hostedService => hostedService.StopIndex);
        }

        /// <summary>
        /// 暂停服务
        /// </summary>
        /// <returns></returns>
        public bool Pause()
        {
            return ServiceAction(CustomerServiceState.Pause, hostedService => hostedService.Pause(), "暂停服务");
        }

        /// <summary>
        /// 继续运行
        /// </summary>
        /// <returns></returns>
        public bool Continue()
        {
            return ServiceAction(CustomerServiceState.Pause, hostedService => hostedService.Continue(), "继续执行中断的服务");
        }

        #endregion
    }
}